#include "task_main.h"
#include "oled.h"
#include "kk_rtc.h"
#include "kk_knob.h"

/* 常量定义 */
#define CURSOR_FLASH_INTERVAL 800    // 光标闪烁间隔(ms)，增加到800ms使闪烁更慢
#define REFRESH_INTERVAL 50          // 主刷新间隔(ms)
#define DISPLAY_UPDATE_INTERVAL 1000 // 显示更新间隔(ms)

/* 类型定义 */
typedef enum
{
    STATE_NORMAL, // 正常显示模式
    STATE_SETTING // 时间设置模式
} DisplayState;

typedef enum
{
    SET_YEAR = 0,
    SET_MONTH,
    SET_DAY,
    SET_HOUR,
    SET_MINUTE,
    SET_SECOND,
    SET_END
} SettingState;

typedef struct
{
    uint8_t x;     // 列坐标 (0-15)
    uint8_t y;     // 行坐标 (0-7)
    uint8_t width; // 字符宽度
} CursorPos;

/* 全局变量 */
static DisplayState display_state = STATE_NORMAL;
static SettingState setting_state = SET_YEAR;
static struct tm setting_time;
static uint8_t need_refresh = 1; // 刷新标志位

/* 光标位置配置 - 根据实际显示精确校准 */
static const CursorPos cursor_pos[] = {
        {2, 1, 1},  // Year (2025) - 年份占4个字符
        {7, 1, 5},  // Month (04) - 月份占2个字符
        {10, 1, 6}, // Day (30) - 日期占2个字符
        {2, 3, 2},  // Hour (12) - 小时占2个字符
        {5, 3, 2},  // Minute (28) - 分钟占2个字符
        {8, 3, 2}   // Second (00) - 秒钟占2个字符
};

/* 星期显示 */
static const char *const weeks[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

/* 显示当前时间 */
void showTime(struct tm *time)
{
    char buf[20];

    /* 日期显示 (2025-04-30) */
    sprintf(buf, "%04d-%02d-%02d", time->tm_year + 1900, time->tm_mon + 1, time->tm_mday);
    OLED_ShowString(2, 1, buf, 16, 0);

    /* 时间显示 (12:28:00) */
    sprintf(buf, "%02d:%02d:%02d", time->tm_hour, time->tm_min, time->tm_sec);
    OLED_ShowString(2, 3, buf, 16, 0);

    /* 星期显示 (Wed) */
    uint8_t x = (128 - strlen(weeks[time->tm_wday]) * 8) / 2;
    OLED_ShowString(x / 8, 5, weeks[time->tm_wday], 16, 0);
}

///* 闪烁光标 */
// void showCursor() {
//     static uint32_t last_tick = 0;
//     static uint8_t visible = 1;
//
//     if (HAL_GetTick() - last_tick >= CURSOR_FLASH_INTERVAL) {
//         last_tick = HAL_GetTick();
//         visible = !visible;
//     }
//
//     const CursorPos *pos = &cursor_pos[setting_state];
//     char str[5];
//
//     switch (setting_state) {
//         case SET_YEAR:  sprintf(str, "%04d", setting_time.tm_year + 1900); break;
//         case SET_MONTH: sprintf(str, "%02d", setting_time.tm_mon + 1); break;
//         case SET_DAY:   sprintf(str, "%02d", setting_time.tm_mday); break;
//         case SET_HOUR:  sprintf(str, "%02d", setting_time.tm_hour); break;
//         case SET_MINUTE:sprintf(str, "%02d", setting_time.tm_min); break;
//         case SET_SECOND:sprintf(str, "%02d", setting_time.tm_sec); break;
//         default: return;
//     }
//
//     OLED_ShowString(pos->x, pos->y, str, 16, visible ? 0 : 1);  // 反相显示光标
//     need_refresh = 1;
// }
//  删除未使用的变量

void showCursor()
{
    static uint32_t last_tick = 0;
    static uint8_t visible = 1;
    static SettingState last_setting_state = SET_END; // 初始化为无效值
    uint32_t current_tick = HAL_GetTick();

    // 检测设置状态是否改变
    if (last_setting_state != setting_state)
    {
        last_setting_state = setting_state;
        need_refresh = 1;         // 强制刷新
        visible = 1;              // 重置光标为可见
        last_tick = current_tick; // 重置闪烁计时器
    }

    // 切换光标可见性
    if (current_tick - last_tick >= CURSOR_FLASH_INTERVAL)
    {
        last_tick = current_tick;
        visible = !visible;
        need_refresh = 1; // 只在光标状态改变时才需要刷新
    }

    // 显示时间和日期（基础显示）
    showTime(&setting_time);

    // 获取当前设置项的位置信息
    const CursorPos *pos = &cursor_pos[setting_state];

    // 为每个设置项绘制对应的光标
    // 首先准备当前设置项的字符串
    char str[5] = {0};
    switch (setting_state)
    {
        case SET_YEAR:
            sprintf(str, "%04d", setting_time.tm_year + 1900);
            break;
        case SET_MONTH:
            sprintf(str, "%02d", setting_time.tm_mon + 1);
            break;
        case SET_DAY:
            sprintf(str, "%02d", setting_time.tm_mday);
            break;
        case SET_HOUR:
            sprintf(str, "%02d", setting_time.tm_hour);
            break;
        case SET_MINUTE:
            sprintf(str, "%02d", setting_time.tm_min);
            break;
        case SET_SECOND:
            sprintf(str, "%02d", setting_time.tm_sec);
            break;
        default:
            return;
    }

    // 绘制光标指示器
    if (visible)
    {
        // 准备下方指示符
        char indicator[17] = "                "; // 16个空格

        // 根据当前设置项的宽度设置指示符
        for (uint8_t i = 0; i < pos->width; i++)
        {
            indicator[i] = '^';
        }

        // 在当前设置项下方显示指示符
        OLED_ShowString(pos->x, pos->y + 1, indicator, 8, 0);

        // 反相显示当前设置项
        OLED_ShowString(pos->x, pos->y, str, 16, 1);
    }
    else
    {
        // 正常显示当前设置项
        OLED_ShowString(pos->x, pos->y, str, 16, 0);

        // 清除下方指示符
        OLED_ShowString(pos->x, pos->y + 1, "                ", 8, 0);
    }
}

/* 编码器回调函数 */
void onKnobForward()
{
    if (display_state == STATE_SETTING)
    {
        need_refresh = 1; // 标记需要刷新显示

        // 根据当前设置状态调整相应的时间值
        switch (setting_state)
        {
            case SET_YEAR:
                setting_time.tm_year++;
                break;
            case SET_MONTH:
                setting_time.tm_mon = (setting_time.tm_mon + 1) % 12;
                // 调整日期以确保有效
                if (setting_time.tm_mday > 28)
                {
                    int max_days = 31;
                    if (setting_time.tm_mon == 1)
                    { // 2月
                        max_days = 28;
                        // 闰年检查
                        int year = setting_time.tm_year + 1900;
                        if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
                            max_days = 29;
                    }
                    else if (setting_time.tm_mon == 3 || setting_time.tm_mon == 5 ||
                             setting_time.tm_mon == 8 || setting_time.tm_mon == 10)
                    {
                        max_days = 30; // 4,6,9,11月
                    }
                    if (setting_time.tm_mday > max_days)
                        setting_time.tm_mday = max_days;
                }
                break;
            case SET_DAY:
                setting_time.tm_mday = (setting_time.tm_mday % 31) + 1;
                break;
            case SET_HOUR:
                setting_time.tm_hour = (setting_time.tm_hour + 1) % 24;
                break;
            case SET_MINUTE:
                setting_time.tm_min = (setting_time.tm_min + 1) % 60;
                break;
            case SET_SECOND:
                setting_time.tm_sec = (setting_time.tm_sec + 1) % 60;
                break;
        }
    }
}

void onKnobBackward()
{
    if (display_state == STATE_SETTING)
    {
        need_refresh = 1; // 标记需要刷新显示

        // 根据当前设置状态调整相应的时间值
        switch (setting_state)
        {
            case SET_YEAR:
                // 年份不能小于1970年
                setting_time.tm_year = (setting_time.tm_year < 70) ? 70 : setting_time.tm_year - 1;
                break;
            case SET_MONTH:
                setting_time.tm_mon = (setting_time.tm_mon - 1 + 12) % 12;
                // 调整日期以确保有效
                if (setting_time.tm_mday > 28)
                {
                    int max_days = 31;
                    if (setting_time.tm_mon == 1)
                    { // 2月
                        max_days = 28;
                        // 闰年检查
                        int year = setting_time.tm_year + 1900;
                        if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
                            max_days = 29;
                    }
                    else if (setting_time.tm_mon == 3 || setting_time.tm_mon == 5 ||
                             setting_time.tm_mon == 8 || setting_time.tm_mon == 10)
                    {
                        max_days = 30; // 4,6,9,11月
                    }
                    if (setting_time.tm_mday > max_days)
                        setting_time.tm_mday = max_days;
                }
                break;
            case SET_DAY:
                setting_time.tm_mday = (setting_time.tm_mday - 2 + 31) % 31 + 1;
                break;
            case SET_HOUR:
                setting_time.tm_hour = (setting_time.tm_hour - 1 + 24) % 24;
                break;
            case SET_MINUTE:
                setting_time.tm_min = (setting_time.tm_min - 1 + 60) % 60;
                break;
            case SET_SECOND:
                setting_time.tm_sec = (setting_time.tm_sec - 1 + 60) % 60;
                break;
        }
    }
}

void onKnobPressed()
{
    if (display_state == STATE_NORMAL)
    {
        // 进入设置模式
        memcpy(&setting_time, KK_RTC_GetTime(), sizeof(struct tm));
        setting_state = SET_YEAR;
        display_state = STATE_SETTING;
        need_refresh = 1; // 强制刷新显示
    }
    else if (display_state == STATE_SETTING)
    {
        // 切换到下一个设置项
        if (++setting_state >= SET_END)
        {
            // 设置完成，保存时间并返回正常模式
            KK_RTC_SetTime(&setting_time);
            display_state = STATE_NORMAL;
        }
        need_refresh = 1; // 强制刷新显示
    }
}

/* 主任务初始化 */
void MainTaskInit()
{
    OLED_Init();
    KK_RTC_Init();
    Knob_Init();
    Knob_SetForwardCallback(onKnobForward);
    Knob_SetBackwardCallback(onKnobBackward);
    Knob_SetPressedCallback(onKnobPressed);

    // 初始化默认时间（2025-04-30 12:28:00 Wed）
    setting_time.tm_year = 125;
    setting_time.tm_mon = 3;
    setting_time.tm_mday = 30;
    setting_time.tm_hour = 12;
    setting_time.tm_min = 28;
    setting_time.tm_sec = 0;
    setting_time.tm_wday = 3;
}

/* 主任务循环 */
void MainTask()
{
    static uint32_t last_refresh = 0;
    static uint32_t last_display_update = 0;
    static struct tm last_time = {0};
    uint32_t current_tick = HAL_GetTick();

    Knob_Loop();

    // 检查是否需要更新显示内容
    if (current_tick - last_display_update >= DISPLAY_UPDATE_INTERVAL)
    {
        last_display_update = current_tick;
        if (display_state == STATE_NORMAL)
        {
            struct tm *now = KK_RTC_GetTime();
            // 只有当时间发生变化时才设置刷新标志
            if (memcmp(now, &last_time, sizeof(struct tm)) != 0)
            {
                memcpy(&last_time, now, sizeof(struct tm));
                need_refresh = 1;
            }
        }
    }

    // 控制刷新率，仅在需要时刷新屏幕
    if ((current_tick - last_refresh >= REFRESH_INTERVAL) && (need_refresh || display_state == STATE_SETTING))
    {
        last_refresh = current_tick;

        OLED_NewFrame();

        if (display_state == STATE_NORMAL)
        {
            showTime(&last_time);
            need_refresh = 0; // 在正常模式下重置刷新标志
        }
        else
        {
            // 在设置模式下，showCursor内部会处理刷新标志
            showCursor();
        }

        OLED_ShowFrame();
    }
}
